//  FilterOptionalCell.swift
//  Automobile
//
//  Created by erkebulan elzhan on 8/2/20.
//  Copyright © 2020 erkebulan elzhan. All rights reserved.


import UIKit
import SnapKit


final class FilterOptionalCell: UITableViewCell, ConfigurableCell {
    
    // MARK: - Outlets
    
    private lazy var mainStack: UIStackView = {
        let stack = UIStackView()
        stack.axis = .vertical
        stack.alignment = .fill
        stack.distribution = .equalSpacing
        stack.spacing = 12.0
        return stack
    }()
    
    private lazy var optionBtn: OptionView = {
        let view = OptionView()
        let tap = UITapGestureRecognizer(target: self, action: #selector(openOptions(sender:)))
        view.addGestureRecognizer(tap)
        return view
    }()
    
    // MARK: - Properties
    
    /// - Index of current cell
    private var index: Int!
    /// - ViewModel of class
    private var filterOptionalModel: FilterOptionalModel!
    /// - Contains all the data about every modal
    private var modals: [ModalView.ModalType: ModalElement] = [:]
    
    
    // MARK: - Actions
    
    /// - Кнопка Выбрать опции была нажата
    @objc func openOptions (sender: UITapGestureRecognizer) {
        self.openOptions()
    }
    
    // MARK: - Init
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.addViews()
        NotificationCenter.default.addObserver(self, selector: #selector(returnData(notification:)), name: NSNotification.Name(rawValue: "sendModal"), object: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "sendModal"), object: nil)
    }

    
    // MARK: - Methods
    
    func configure(data object: Filter.FilterOptional, index: Int) {
        self.filterOptionalModel = FilterOptionalModel(filterOptional: object)
        self.setUpFields()
    }
    
    func returnData() -> Filter.FilterOptional {
        return  filterOptionalModel.filterOptional
    }
}





// MARK: - Delegate

extension FilterOptionalCell {
    
    /// Modal Element (like a UIButton) was clicked
    /// - Parameter modal: [probeg, color, power, price and e.t.c]
    private func openModal (for modal: ModalView.ModalType) {
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "openModal"), object: nil, userInfo: ["modal": modal])
    }
    
    /// Navigate to another View Controller, to select options
    private func openOptions () {
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "openOptions"), object: nil, userInfo: ["value": true])
    }
    
    /// Callback from Modal View
    /// - Parameter notification: Contains information about selected items
    @objc private func returnData (notification: NSNotification) {
        if let userInfo = notification.userInfo {
            let modal = userInfo["type"] as! ModalView.ModalType
            if filterOptionalModel.pickerData[modal] != nil {
                let data = userInfo["data"] as! [Double?]
                self.updatePickers(modal: modal, data: data)
            } else {
                let data = userInfo["data"] as! [ModalView.ModalData]
                self.updateTableViews(modal: modal, data: data)
            }
        }
    }
}


extension FilterOptionalCell {
    
    /// Updating fields in table view cell
    /// - Parameters:
    ///   - modal: Modal's type: (Пробег, Цена, and other range types)
    ///   - data: [<#from#>, <#to#>]: [Int, Int]
    private func updatePickers (modal: ModalView.ModalType, data: [Double?]) {
        let intFrom = data.count > 0 && data[0] != nil ? Int(data[0]!) : nil
        let intTo = data.count > 1 && data[1] != nil ? Int(data[1]!) : nil
        
        if modal == .probeg {
            filterOptionalModel.updateProbeg(from: intFrom, to: intTo) 
            self.modals[modal]?.updateUI(value: filterOptionalModel.probegText)
        } else if modal == .power {
            filterOptionalModel.updatePower(powerOt: intFrom, powerDo: intTo)
            self.modals[modal]?.updateUI(value: filterOptionalModel.powerText)
        } else if modal == .year {
            filterOptionalModel.updateYear(yearOt: intFrom, yearDo: intTo)
            self.modals[modal]?.updateUI(value: filterOptionalModel.yearText)
        } else if modal == .volume {
            filterOptionalModel.updateVolume(from: data[0], to: data[1])
            self.modals[modal]?.updateUI(value: filterOptionalModel.volumeText)
        } else if modal == .expenditures {
            filterOptionalModel.updateExpenditure(from: intFrom, to: intTo)
            self.modals[modal]?.updateUI(value: filterOptionalModel.expenditureText)
        } else if modal == .price {
            filterOptionalModel.updatePrice(from: intFrom, to: intTo)
            self.modals[modal]?.updateUI(value: filterOptionalModel.priceText)
        }
    }
    
    /// Reloading UITableViewController
    /// - Parameters:
    ///   - modal: Modal's type: (Пробег, Цена, and other range types)
    ///   - data: [ModalView.ModalData] - multiple selected items, contains  <#name#>,, <#id#>
    private func updateTableViews (modal: ModalView.ModalType, data: [ModalView.ModalData]) {
        let dataValues = data.map { $0.name }
        switch modal {
        case .privod:
            self.filterOptionalModel.updatePrivod(privod: data)
        case .color:
            self.filterOptionalModel.updateColor(color: data)
        case .korobka:
            self.filterOptionalModel.updateKorobka(korobka: data)
        case .kuzov:
            self.filterOptionalModel.updateKuzov(kuzov: data)
        case .dvigatel:
            self.filterOptionalModel.updateDvigatel(dvigatel: data)
        case .rule:
            self.filterOptionalModel.updateRule(rule: data)
            
        default:
            break
        }
        modals[modal]?.updateUI(value: dataValues.joined(separator: ", "))
    }
    
    
    private func setUpFields () {
        for (_, key) in self.getKeys().enumerated() {
            let rangeKeys: [ModalView.ModalType: String] = [
                .year: filterOptionalModel.yearText,
                .power: filterOptionalModel.powerText,
                .probeg: filterOptionalModel.probegText,
                .volume: filterOptionalModel.volumeText,
                .expenditures: filterOptionalModel.expenditureText,
                .price: filterOptionalModel.priceText
            ]
            
            if rangeKeys.keys.contains(key) {
                modals[key]?.updateUI(value: rangeKeys[key])
            } else {
                if filterOptionalModel.filterOptional[key] is [ModalView.ModalData] {
                    let dataValues = (filterOptionalModel.filterOptional[key] as! [ModalView.ModalData]).map { $0.name }
                    modals[key]?.updateUI(value: dataValues.joined(separator: ", "))
                } else {
                    if let _data = filterOptionalModel.filterOptional[key] as? [String] {
                        modals[key]?.updateUI(value: _data.joined(separator: ", "))
                    }
                }
            }
        }
    }
    
    private func getKeys () -> [ModalView.ModalType] {
        return Array(ModalView.ModalType.allCases.prefix(ModalView.ModalType.allCases.count - 3))
    }
}


// MARK: - Adding views to superview

extension FilterOptionalCell {
    
    private func addViews () {
        self.contentView.addSubview(mainStack)
        self.contentView.addSubview(optionBtn)
        
        for modal in self.getKeys() {
            let modalBtn = createModalButton(modal: modal)
            modals[modal] = modalBtn
            mainStack.addArrangedSubview(modalBtn)
        }
        
        mainStack.addArrangedSubview(optionBtn)
        self.applyConstraints()
    }
    
    private func applyConstraints() {
        mainStack.snp.makeConstraints { (make) in
            make.top.bottom.equalToSuperview().inset(20)
            make.leading.trailing.equalToSuperview().inset(16)
        }
        optionBtn.snp.makeConstraints { (make) in
            make.height.equalTo(64)
        }
    }

    /// Creating modal opener button
    /// - Parameter modal: Type of modal (Пробег, цена и тд)
    /// - Returns: Modal Element view
    private func createModalButton (modal: ModalView.ModalType) -> ModalElement {
        let btn = ModalElement()
        btn.updateUI(value: nil, placeholder: modal.rawValue)
        btn.modal = modal
        btn.delegate = self
        btn.snp.makeConstraints { (make) in
            make.height.equalTo(48)
        }
        return btn
    }
}

extension FilterOptionalCell: ModalElementProtocol {
    func didClear(modal: ModalView.ModalType) {
        if filterOptionalModel.pickerData[modal] != nil {
            self.updatePickers(modal: modal, data: [])
        } else {
            self.updateTableViews(modal: modal, data: [])
        }
    }
    func selectElement(modal: ModalView.ModalType?, customID: Int?) {
        self.openModal(for: modal!)
    }
}


// MARK: - Выбрать опции Button

final class OptionView: UIView {
    lazy private var stack: UIStackView = {
        let stack = UIStackView()
        stack.axis = .vertical
        stack.alignment = .leading
        stack.distribution = .fillEqually
        stack.spacing = 4
        return stack
    }()
    lazy private var titleLbl: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 15, weight: .medium)
        label.text = "Выбрать опции"
        label.textColor = .white
        return label
    }()
    lazy private var arrowBtn: UIButton = {
        let btn = UIButton()
        btn.setImage(UIImage(named: "arrow")?.sd_tintedImage(with: .white), for: .normal)
        return btn
    }()
    
    init () {
        super.init(frame: .zero)
        self.addView()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func addView () {
        self.backgroundColor = .blueColor
        self.layer.cornerRadius = 10
        
        
        self.addSubview(stack)
        self.addSubview(arrowBtn)
        stack.addArrangedSubview(titleLbl)
        
        self.addConstraints()
    }
    
    private func addConstraints () {
        arrowBtn.snp.makeConstraints { (make) in
            make.trailing.equalToSuperview().offset(-16)
            make.width.equalTo(8)
            make.height.equalTo(13)
            make.centerY.equalToSuperview()
        }
        stack.snp.makeConstraints { (make) in
            make.leading.equalToSuperview().inset(16)
            make.trailing.equalTo(arrowBtn.snp.leading).offset(-16)
            make.height.equalTo(34)
            make.centerY.equalToSuperview()
        }
    }
}
